﻿using System;
using System.Text;

namespace Codemonk.Common.Emit
{
    /// <summary>
    /// 基于参数生成的hash
    /// 不支持同函数名同参数个数但是参数类型不同的函数重载
    /// </summary>
    internal sealed class ParameterHash
    {
        private readonly int hash = 0;
        public ParameterHash(object[] parameters)
        {
            if (parameters != null && parameters.Length != 0)
            {
                StringBuilder builder = new StringBuilder();
                foreach (var parameter in parameters)
                {
                    if (parameter == null) builder.Append("1");
                    else
                    {
                        var type = parameter.GetType();
                        if (type.IsValueType) builder.Append("0");
                        else builder.Append("1");
                    }
                    builder.Append(",");
                }
                var result = builder.ToString();
                hash = result.GetHashCode();
            }
        }
        public ParameterHash(Type[] types)
        {
            if (types != null && types.Length != 0)
            {
                StringBuilder builder = new StringBuilder();
                foreach (var type in types)
                {
                    if (type == null) throw new NullReferenceException();
                    if (type.IsValueType) builder.Append("0");
                    else builder.Append("1");
                    builder.Append(",");
                }
                var result = builder.ToString();
                hash = result.GetHashCode();
            }
        }


        public override int GetHashCode()
        {
            return hash;
        }
        public override bool Equals(object obj)
        {
            var ph = obj as ParameterHash;
            if (object.Equals(ph, null)) return false;
            return ph.hash == hash;
        }
        public static bool operator ==(ParameterHash ph1, ParameterHash ph2)
        {
            if (object.Equals(ph1, null) && object.Equals(ph2, null)) return true;
            if (!object.Equals(ph1, null) && object.Equals(ph2, null)) return false;
            if (object.Equals(ph1, null) && !object.Equals(ph2, null)) return false;
            return ph1.Equals(ph2);
        }
        public static bool operator !=(ParameterHash ph1, ParameterHash ph2)
        {
            return !(ph1 == ph2);
        }
    }
}
